﻿using System;
using NHibernate;

namespace Data.NHibernateProvider
{
    public sealed class SessionProvider
    {
        public static ISession GetSession
        {
            get { return BuildSession(); }
        }

        public static void MakeOperation(Action<ISession> operation)
        {
            using (ISession session = BuildSession())
            {
                operation(session);
            }
        }

        public static TResult MakeOperation<TResult>(Func<ISession, TResult> operation)
        {
            using (ISession session = BuildSession())
            {
                return operation(session);
            }
        }

        public static void MakeOperationInTransaction(Action<ISession> operation)
        {
            using (ISession session = GetSession)
            {
                using (ITransaction transaction = session.BeginTransaction())
                {
                    try
                    {
                        operation(session);

                        if (transaction != null && transaction.IsActive)
                        {
                            transaction.Commit();
                        }
                        else
                        {
                            session.Flush();
                        }
                    }
                    catch (Exception)
                    {
                        if (transaction != null && transaction.IsActive)
                        {
                            transaction.Rollback();
                        }
                        throw;
                    }
                }
            }
        }

        public static TResult MakeOperationInTransaction<TResult>(Func<ISession, TResult> operation)
        {
            TResult result;
            using (ISession session = GetSession)
            {
                using (ITransaction transaction = session.BeginTransaction())
                {
                    try
                    {
                        result = operation(session);

                        if (transaction != null && transaction.IsActive)
                        {
                            transaction.Commit();
                        }
                        else
                        {
                            session.Flush();
                        }
                    }
                    catch (Exception)
                    {
                        if (transaction != null && transaction.IsActive)
                        {
                            transaction.Rollback();
                        }
                        throw;
                    }
                }
            }
            return result;
        }

        private static ISession BuildSession()
        {
            ISessionFactory sessionFactory = SessionFactory.GetSessionFactory;
            ISession session = sessionFactory.OpenSession(new CustomInterceptor());
            return session;
        }
    }
}